/* Startup code for ARM & ELF
   Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301, USA.  */

/* This is the canonical entry point, usually the first thing in the text
   segment.

	Note that the code in the .init section has already been run.
	This includes _init and _libc_init


	At this entry point, most registers' values are unspecified, except:

   a1		Contains a function pointer to be registered with `atexit'.
		This is how the dynamic linker arranges to have DT_FINI
		functions called for shared libraries that have been loaded
		before this code runs.

   sp		The stack contains the arguments and environment:
		0(sp)			argc
		4(sp)			argv[0]
		...
		(4*argc)(sp)		NULL
		(4*(argc+1))(sp)	envp[0]
		...
					NULL
*/

	.text
	.globl _dynamic_start
	.type _dynamic_start,#function
_dynamic_start:
.ifdef __thumb__
         ldr r7,=__dl_fini
         str a1,[r7]
.else
         ldr ip,=__dl_fini
         str a1,[ip]
.endif
         b _start

	.text
	.globl _start
	.type _start,#function
_start:
.ifdef __thumb__
        pop {a2}

        /* Pop argc off the stack and save a pointer to argv */
	ldr r7,=operatingsystem_parameter_argc
	str a2,[r7]

	ldr r7,=operatingsystem_parameter_argv
        mov a3,sp
   	str a3,[r7]

	/* calc envp */
	ldr r7,=operatingsystem_parameter_envp
	add a2,a2,#1
        lsl a2,a2,#2
	add a2,sp,a2
        str a2,[r7]

        /* Save initial stackpointer */
	ldr r7,=__stkptr
        str a3,[r7]

	/* Clear the frame pointer since this is the outermost frame.  */
	mov r7, #0
.else
	mov fp, #0
	ldmia   sp!, {a2}

        /* Pop argc off the stack and save a pointer to argv */
	ldr ip,=operatingsystem_parameter_argc
	ldr a3,=operatingsystem_parameter_argv
	str a2,[ip]

	/* calc envp */
	add a2,a2,#1
	add a2,sp,a2,LSL #2
	ldr ip,=operatingsystem_parameter_envp

	str sp,[a3]
   	str a2,[ip]

        /* Save initial stackpointer */
	ldr ip,=__stkptr
	str sp,[ip]
.endif

        /* align sp again to 8 byte boundary, needed by eabi */
        sub sp,sp,#4

	/* Let the libc call main and exit with its return code.  */
	bl PASCALMAIN

	.globl  _haltproc
    .type   _haltproc,#function
_haltproc:
        /* r0 contains exitcode */
.ifdef __thumb__
        ldr r0,=operatingsystem_result
        ldr r0,[r0]
        mov r7,#248  /* exit group call */
	swi 0x0
.else
	swi 0x900001
.endif
	b _haltproc

	.globl  _haltproc_eabi
        .type   _haltproc_eabi,#function
_haltproc_eabi:
        ldr r0,=__dl_fini
        ldr r0,[r0]
        cmp r0,#0

.ifdef __thumb__
        beq .Lnobranch
        /* only branch if not equal zero */
        mov lr,pc
        bx  r0     /* we require armv5 anyway, so use bx here */
.Lnobranch:
.else
        /* only branch if not equal zero */
        movne lr,pc
        bxne  r0     /* we require armv5 anyway, so use bx here */
.endif

.Lloop:
        ldr r0,=operatingsystem_result
        ldr r0,[r0]
        mov r7,#248  /* exit group call */
	swi 0x0
	b .Lloop

	/* Define a symbol for the first piece of initialized data.  */
	.data
	.globl __data_start
__data_start:
	.long 0
	.weak data_start
	data_start = __data_start

.bss
        .comm __dl_fini,4
        .comm __stkptr,4

        .comm operatingsystem_parameter_envp,4
        .comm operatingsystem_parameter_argc,4
        .comm operatingsystem_parameter_argv,4

	.section ".comment"
	.byte 0
	.ascii "generated by FPC http://www.freepascal.org\0"

/* We need this stuff to make gdb behave itself, otherwise
   gdb will chokes with SIGILL when trying to debug apps.
*/
        .section ".note.ABI-tag", "a"
        .align 4
        .long 1f - 0f
        .long 3f - 2f
        .long  1
0:      .asciz "GNU"
1:      .align 4
2:      .long 0
        .long 2,0,0
3:      .align 4

.section .note.GNU-stack,"",%progbits
